package behavior;

import arena.Node;

/**
 * CardinalBehavior is a single movement behavior that will move a
 * robot in 1 of 4 possible cardinal directions (North, South, East, West).
 *
 * @author      Gabriel Loewen
 * @author      James Weston
 * @author      Jackie O'Quinn
 */
public class CardinalBehavior extends Behavior {

    // The next node to move the robot to.
    private Node nextNode;
    boolean found = false;
    String goal;
    char direction;

    /**
     * Default constructor
     */
    public CardinalBehavior() {
        super("Cardinal Directions");
    }

    /**
     * Because this behavior does not require any searching progress of
     * the behavior is irrelavent and defaults to 100%.
     */
    @Override
    public double getProgress() {
        return 100;
    }

    /**
     * Irrelavent method.
     */
    @Override
    public void resetProgress() {
    }

    /**
     * Determines whether or not the next move will be valid.  Validity is
     * determined by the existence of the next node.
     */
    public boolean isValidMove() {
        if (nextNode == null) {
            return false;
        }
        return nodeExists(nextNode.toString());
    }

    /**
     * Calculates the next node to move the robot to.  This is determined by
     * the goal parameter.  In this case the goal is a 1 character String with
     * 4 valid possibilities of "N", "S", "E", or "W".  All other Strings are
     * rejected.
     *
     * @param   goal    A cardinal direction of 1 character.
     * @param   cancel  Boolean variable that cancels the algorithm if the user
     * presses the cancel button.
     */
    @Override
    public void getPath(String goal, boolean cancel) {
        if (cancel) {
            found = false;
            return;
        }
        direction = goal.toUpperCase().charAt(0);
        found = true;
        switch (direction) {
            case 'N':
                nextNode = robot.getArena().nodeMap.get(robot.getLocation().x + "," +
                        (robot.getLocation().y + 1));
                break;
            case 'S':
                nextNode = robot.getArena().nodeMap.get(robot.getLocation().x + "," +
                        (robot.getLocation().y - 1));
                break;
            case 'E':
                nextNode = robot.getArena().nodeMap.get((robot.getLocation().x + 1) + "," +
                        robot.getLocation().y);
                break;
            case 'W':
                nextNode = robot.getArena().nodeMap.get((robot.getLocation().x - 1) + "," +
                        robot.getLocation().y);
                break;
            default:
                found = false;
                break;
        }
    }

    /**
     * Returns the true if the next node is available.  False otherwise.
     */
    @Override
    public boolean hasMove() {
        return found;
    }

    /**
     * Returns an integer array representing the next move.
     * The array is formatted correctly using the Util class.
     *
     * @see Util
     */
    @Override
    public int[] nextMove() {
        if (!nextNode.isOccupied) {
            found = false;
            return Util.getMoveData(robot.heading, robot.getLocation().x, robot.getLocation().y, direction);
        }
        return new int[]{'X'};
    }
}
